﻿namespace Hardcodet.Wpf.TaskbarNotification
{
    using Hardcodet.Wpf.TaskbarNotification.Interop;
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Runtime.CompilerServices;
    using System.Threading;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Controls.Primitives;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Threading;

    public class TaskbarIcon : FrameworkElement, IDisposable
    {
        private readonly Timer balloonCloseTimer;
        public static readonly RoutedEvent BalloonClosingEvent = EventManager.RegisterRoutedEvent("BalloonClosing", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent BalloonShowingEvent = EventManager.RegisterRoutedEvent("BalloonShowing", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public const string CategoryName = "NotifyIcon";
        public static readonly DependencyProperty CustomBalloonProperty = CustomBalloonPropertyKey.DependencyProperty;
        private static readonly DependencyPropertyKey CustomBalloonPropertyKey = DependencyProperty.RegisterReadOnly("CustomBalloon", typeof(Popup), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null));
        private Action delayedTimerAction;
        public static readonly DependencyProperty DoubleClickCommandParameterProperty = DependencyProperty.Register("DoubleClickCommandParameter", typeof(object), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null));
        public static readonly DependencyProperty DoubleClickCommandProperty = DependencyProperty.Register("DoubleClickCommand", typeof(ICommand), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null));
        public static readonly DependencyProperty DoubleClickCommandTargetProperty = DependencyProperty.Register("DoubleClickCommandTarget", typeof(IInputElement), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null));
        private System.Drawing.Icon icon;
        private NotifyIconData iconData;
        public static readonly DependencyProperty IconSourceProperty = DependencyProperty.Register("IconSource", typeof(ImageSource), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(TaskbarIcon.IconSourcePropertyChanged)));
        public static readonly DependencyProperty LeftClickCommandParameterProperty = DependencyProperty.Register("LeftClickCommandParameter", typeof(object), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null));
        public static readonly DependencyProperty LeftClickCommandProperty = DependencyProperty.Register("LeftClickCommand", typeof(ICommand), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null));
        public static readonly DependencyProperty LeftClickCommandTargetProperty = DependencyProperty.Register("LeftClickCommandTarget", typeof(IInputElement), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null));
        public static readonly DependencyProperty MenuActivationProperty = DependencyProperty.Register("MenuActivation", typeof(PopupActivationMode), typeof(TaskbarIcon), new FrameworkPropertyMetadata(PopupActivationMode.RightClick));
        private readonly WindowMessageSink messageSink = (Util.IsDesignMode ? WindowMessageSink.CreateEmpty() : new WindowMessageSink(NotifyIconVersion.Win95));
        public static readonly DependencyProperty ParentTaskbarIconProperty = DependencyProperty.RegisterAttached("ParentTaskbarIcon", typeof(TaskbarIcon), typeof(TaskbarIcon));
        public static readonly DependencyProperty PopupActivationProperty = DependencyProperty.Register("PopupActivation", typeof(PopupActivationMode), typeof(TaskbarIcon), new FrameworkPropertyMetadata(PopupActivationMode.LeftClick));
        public static readonly RoutedEvent PopupOpenedEvent = EventManager.RegisterRoutedEvent("PopupOpened", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent PreviewTrayContextMenuOpenEvent = EventManager.RegisterRoutedEvent("PreviewTrayContextMenuOpen", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent PreviewTrayPopupOpenEvent = EventManager.RegisterRoutedEvent("PreviewTrayPopupOpen", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent PreviewTrayToolTipCloseEvent = EventManager.RegisterRoutedEvent("PreviewTrayToolTipClose", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent PreviewTrayToolTipOpenEvent = EventManager.RegisterRoutedEvent("PreviewTrayToolTipOpen", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        private readonly Timer singleClickTimer;
        public static readonly RoutedEvent ToolTipCloseEvent = EventManager.RegisterRoutedEvent("ToolTipClose", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent ToolTipOpenedEvent = EventManager.RegisterRoutedEvent("ToolTipOpened", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly DependencyProperty ToolTipTextProperty = DependencyProperty.Register("ToolTipText", typeof(string), typeof(TaskbarIcon), new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(TaskbarIcon.ToolTipTextPropertyChanged)));
        public static readonly RoutedEvent TrayBalloonTipClickedEvent = EventManager.RegisterRoutedEvent("TrayBalloonTipClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayBalloonTipClosedEvent = EventManager.RegisterRoutedEvent("TrayBalloonTipClosed", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayBalloonTipShownEvent = EventManager.RegisterRoutedEvent("TrayBalloonTipShown", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayContextMenuOpenEvent = EventManager.RegisterRoutedEvent("TrayContextMenuOpen", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayLeftMouseDownEvent = EventManager.RegisterRoutedEvent("TrayLeftMouseDown", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayLeftMouseUpEvent = EventManager.RegisterRoutedEvent("TrayLeftMouseUp", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayMiddleMouseDownEvent = EventManager.RegisterRoutedEvent("TrayMiddleMouseDown", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayMiddleMouseUpEvent = EventManager.RegisterRoutedEvent("TrayMiddleMouseUp", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayMouseDoubleClickEvent = EventManager.RegisterRoutedEvent("TrayMouseDoubleClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayMouseMoveEvent = EventManager.RegisterRoutedEvent("TrayMouseMove", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayPopupOpenEvent = EventManager.RegisterRoutedEvent("TrayPopupOpen", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly DependencyProperty TrayPopupProperty = DependencyProperty.Register("TrayPopup", typeof(UIElement), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(TaskbarIcon.TrayPopupPropertyChanged)));
        public static readonly DependencyProperty TrayPopupResolvedProperty = TrayPopupResolvedPropertyKey.DependencyProperty;
        private static readonly DependencyPropertyKey TrayPopupResolvedPropertyKey = DependencyProperty.RegisterReadOnly("TrayPopupResolved", typeof(Popup), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null));
        public static readonly RoutedEvent TrayRightMouseDownEvent = EventManager.RegisterRoutedEvent("TrayRightMouseDown", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayRightMouseUpEvent = EventManager.RegisterRoutedEvent("TrayRightMouseUp", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayToolTipCloseEvent = EventManager.RegisterRoutedEvent("TrayToolTipClose", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly RoutedEvent TrayToolTipOpenEvent = EventManager.RegisterRoutedEvent("TrayToolTipOpen", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TaskbarIcon));
        public static readonly DependencyProperty TrayToolTipProperty = DependencyProperty.Register("TrayToolTip", typeof(UIElement), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(TaskbarIcon.TrayToolTipPropertyChanged)));
        public static readonly DependencyProperty TrayToolTipResolvedProperty = TrayToolTipResolvedPropertyKey.DependencyProperty;
        private static readonly DependencyPropertyKey TrayToolTipResolvedPropertyKey = DependencyProperty.RegisterReadOnly("TrayToolTipResolved", typeof(ToolTip), typeof(TaskbarIcon), new FrameworkPropertyMetadata(null));

        public event RoutedEventHandler PreviewTrayContextMenuOpen
        {
            add
            {
                base.AddHandler(PreviewTrayContextMenuOpenEvent, value);
            }
            remove
            {
                base.RemoveHandler(PreviewTrayContextMenuOpenEvent, value);
            }
        }

        public event RoutedEventHandler PreviewTrayPopupOpen
        {
            add
            {
                base.AddHandler(PreviewTrayPopupOpenEvent, value);
            }
            remove
            {
                base.RemoveHandler(PreviewTrayPopupOpenEvent, value);
            }
        }

        public event RoutedEventHandler PreviewTrayToolTipClose
        {
            add
            {
                base.AddHandler(PreviewTrayToolTipCloseEvent, value);
            }
            remove
            {
                base.RemoveHandler(PreviewTrayToolTipCloseEvent, value);
            }
        }

        public event RoutedEventHandler PreviewTrayToolTipOpen
        {
            add
            {
                base.AddHandler(PreviewTrayToolTipOpenEvent, value);
            }
            remove
            {
                base.RemoveHandler(PreviewTrayToolTipOpenEvent, value);
            }
        }

        public event RoutedEventHandler TrayBalloonTipClicked
        {
            add
            {
                base.AddHandler(TrayBalloonTipClickedEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayBalloonTipClickedEvent, value);
            }
        }

        public event RoutedEventHandler TrayBalloonTipClosed
        {
            add
            {
                base.AddHandler(TrayBalloonTipClosedEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayBalloonTipClosedEvent, value);
            }
        }

        public event RoutedEventHandler TrayBalloonTipShown
        {
            add
            {
                base.AddHandler(TrayBalloonTipShownEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayBalloonTipShownEvent, value);
            }
        }

        public event RoutedEventHandler TrayContextMenuOpen
        {
            add
            {
                base.AddHandler(TrayContextMenuOpenEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayContextMenuOpenEvent, value);
            }
        }

        [Category("NotifyIcon")]
        public event RoutedEventHandler TrayLeftMouseDown
        {
            add
            {
                base.AddHandler(TrayLeftMouseDownEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayLeftMouseDownEvent, value);
            }
        }

        public event RoutedEventHandler TrayLeftMouseUp
        {
            add
            {
                base.AddHandler(TrayLeftMouseUpEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayLeftMouseUpEvent, value);
            }
        }

        public event RoutedEventHandler TrayMiddleMouseDown
        {
            add
            {
                base.AddHandler(TrayMiddleMouseDownEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayMiddleMouseDownEvent, value);
            }
        }

        public event RoutedEventHandler TrayMiddleMouseUp
        {
            add
            {
                base.AddHandler(TrayMiddleMouseUpEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayMiddleMouseUpEvent, value);
            }
        }

        public event RoutedEventHandler TrayMouseDoubleClick
        {
            add
            {
                base.AddHandler(TrayMouseDoubleClickEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayMouseDoubleClickEvent, value);
            }
        }

        public event RoutedEventHandler TrayMouseMove
        {
            add
            {
                base.AddHandler(TrayMouseMoveEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayMouseMoveEvent, value);
            }
        }

        public event RoutedEventHandler TrayPopupOpen
        {
            add
            {
                base.AddHandler(TrayPopupOpenEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayPopupOpenEvent, value);
            }
        }

        public event RoutedEventHandler TrayRightMouseDown
        {
            add
            {
                base.AddHandler(TrayRightMouseDownEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayRightMouseDownEvent, value);
            }
        }

        public event RoutedEventHandler TrayRightMouseUp
        {
            add
            {
                base.AddHandler(TrayRightMouseUpEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayRightMouseUpEvent, value);
            }
        }

        public event RoutedEventHandler TrayToolTipClose
        {
            add
            {
                base.AddHandler(TrayToolTipCloseEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayToolTipCloseEvent, value);
            }
        }

        public event RoutedEventHandler TrayToolTipOpen
        {
            add
            {
                base.AddHandler(TrayToolTipOpenEvent, value);
            }
            remove
            {
                base.RemoveHandler(TrayToolTipOpenEvent, value);
            }
        }

        static TaskbarIcon()
        {
            PropertyMetadata typeMetadata = new PropertyMetadata(Visibility.Visible, new PropertyChangedCallback(TaskbarIcon.VisibilityPropertyChanged));
            UIElement.VisibilityProperty.OverrideMetadata(typeof(TaskbarIcon), typeMetadata);
            typeMetadata = new FrameworkPropertyMetadata(new PropertyChangedCallback(TaskbarIcon.DataContextPropertyChanged));
            FrameworkElement.DataContextProperty.OverrideMetadata(typeof(TaskbarIcon), typeMetadata);
            typeMetadata = new FrameworkPropertyMetadata(new PropertyChangedCallback(TaskbarIcon.ContextMenuPropertyChanged));
            FrameworkElement.ContextMenuProperty.OverrideMetadata(typeof(TaskbarIcon), typeMetadata);
        }

        public TaskbarIcon()
        {
            this.iconData = NotifyIconData.CreateDefault(this.messageSink.MessageWindowHandle);
            this.CreateTaskbarIcon();
            this.messageSink.MouseEventReceived += new Action<MouseEvent>(this.OnMouseEvent);
            this.messageSink.TaskbarCreated += new Action(this.OnTaskbarCreated);
            this.messageSink.ChangeToolTipStateRequest += new Action<bool>(this.OnToolTipChange);
            this.messageSink.BallonToolTipChanged += new Action<bool>(this.OnBalloonToolTipChanged);
            this.singleClickTimer = new Timer(new TimerCallback(this.DoSingleClickAction));
            this.balloonCloseTimer = new Timer(new TimerCallback(this.CloseBalloonCallback));
            if (Application.Current != null)
            {
                Application.Current.Exit += new ExitEventHandler(this.OnExit);
            }
        }

        public static void AddBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler)
        {
            RoutedEventHelper.AddHandler(element, BalloonClosingEvent, handler);
        }

        public static void AddBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler)
        {
            RoutedEventHelper.AddHandler(element, BalloonShowingEvent, handler);
        }

        public static void AddPopupOpenedHandler(DependencyObject element, RoutedEventHandler handler)
        {
            RoutedEventHelper.AddHandler(element, PopupOpenedEvent, handler);
        }

        public static void AddToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler)
        {
            RoutedEventHelper.AddHandler(element, ToolTipCloseEvent, handler);
        }

        public static void AddToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler)
        {
            RoutedEventHelper.AddHandler(element, ToolTipOpenedEvent, handler);
        }

        public void CloseBalloon()
        {
            if (!this.IsDisposed)
            {
                if (!Application.Current.Dispatcher.CheckAccess())
                {
                    Action method = new Action(this.CloseBalloon);
                    Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, method);
                }
                else
                {
                    lock (this)
                    {
                        this.balloonCloseTimer.Change(-1, -1);
                        Popup customBalloon = this.CustomBalloon;
                        if (customBalloon != null)
                        {
                            UIElement child = customBalloon.Child;
                            if (!RaiseBalloonClosingEvent(child, this).Handled)
                            {
                                customBalloon.IsOpen = false;
                                if (child != null)
                                {
                                    SetParentTaskbarIcon(child, null);
                                }
                            }
                            this.SetCustomBalloon(null);
                        }
                    }
                }
            }
        }

        private void CloseBalloonCallback(object state)
        {
            if (!this.IsDisposed)
            {
                Action method = new Action(this.CloseBalloon);
                Application.Current.Dispatcher.Invoke(method, new object[0]);
            }
        }

        private static void ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarIcon) d).OnContextMenuPropertyChanged(e);
        }

        private void CreateCustomToolTip()
        {
            ToolTip trayToolTip = this.TrayToolTip as ToolTip;
            if ((trayToolTip == null) && (this.TrayToolTip != null))
            {
                trayToolTip = new ToolTip {
                    Placement = PlacementMode.Mouse,
                    HasDropShadow = false,
                    BorderThickness = new Thickness(0.0),
                    Background = System.Windows.Media.Brushes.Transparent,
                    StaysOpen = true,
                    Content = this.TrayToolTip
                };
            }
            else if ((trayToolTip == null) && !string.IsNullOrEmpty(this.ToolTipText))
            {
                trayToolTip = new ToolTip {
                    Content = this.ToolTipText
                };
            }
            if (trayToolTip != null)
            {
                this.UpdateDataContext(trayToolTip, null, base.DataContext);
            }
            this.SetTrayToolTipResolved(trayToolTip);
        }

        private void CreatePopup()
        {
            Popup trayPopup = this.TrayPopup as Popup;
            if ((trayPopup == null) && (this.TrayPopup != null))
            {
                trayPopup = new Popup {
                    AllowsTransparency = true,
                    PopupAnimation = PopupAnimation.None,
                    Child = this.TrayPopup,
                    Placement = PlacementMode.AbsolutePoint,
                    StaysOpen = false
                };
            }
            if (trayPopup != null)
            {
                this.UpdateDataContext(trayPopup, null, base.DataContext);
            }
            this.SetTrayPopupResolved(trayPopup);
        }

        private void CreateTaskbarIcon()
        {
            lock (this)
            {
                if (!this.IsTaskbarIconCreated)
                {
                    if (!Util.WriteIconData(ref this.iconData, NotifyCommand.Add, IconDataMembers.Tip | IconDataMembers.Icon | IconDataMembers.Message))
                    {
                        throw new Win32Exception("Could not create icon data");
                    }
                    this.SetVersion();
                    this.messageSink.Version = (NotifyIconVersion) ((int) this.iconData.VersionOrTimeout);
                    this.IsTaskbarIconCreated = true;
                }
            }
        }

        private static void DataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarIcon) d).OnDataContextPropertyChanged(e);
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (!this.IsDisposed && disposing)
            {
                lock (this)
                {
                    this.IsDisposed = true;
                    Application.Current.Exit -= new ExitEventHandler(this.OnExit);
                    this.singleClickTimer.Dispose();
                    this.balloonCloseTimer.Dispose();
                    this.messageSink.Dispose();
                    this.RemoveTaskbarIcon();
                }
            }
        }

        private void DoSingleClickAction(object state)
        {
            if (!this.IsDisposed)
            {
                Action delayedTimerAction = this.delayedTimerAction;
                if (delayedTimerAction != null)
                {
                    this.delayedTimerAction = null;
                    Application.Current.Dispatcher.Invoke(delayedTimerAction, new object[0]);
                }
            }
        }

        private void EnsureNotDisposed()
        {
            if (this.IsDisposed)
            {
                throw new ObjectDisposedException(base.Name ?? base.GetType().FullName);
            }
        }

        ~TaskbarIcon()
        {
            this.Dispose(false);
        }

        public static TaskbarIcon GetParentTaskbarIcon(DependencyObject d)
        {
            return (TaskbarIcon) d.GetValue(ParentTaskbarIconProperty);
        }

        public void HideBalloonTip()
        {
            this.EnsureNotDisposed();
            this.iconData.BalloonText = this.iconData.BalloonTitle = string.Empty;
            Util.WriteIconData(ref this.iconData, NotifyCommand.Modify, IconDataMembers.Info);
        }

        private static void IconSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarIcon) d).OnIconSourcePropertyChanged(e);
        }

        private void OnBalloonToolTipChanged(bool visible)
        {
            if (visible)
            {
                this.RaiseTrayBalloonTipShownEvent();
            }
            else
            {
                this.RaiseTrayBalloonTipClosedEvent();
            }
        }

        private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != null)
            {
                SetParentTaskbarIcon((DependencyObject) e.OldValue, null);
            }
            if (e.NewValue != null)
            {
                SetParentTaskbarIcon((DependencyObject) e.NewValue, this);
            }
            this.UpdateDataContext((ContextMenu) e.NewValue, null, base.DataContext);
        }

        private void OnDataContextPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            object newValue = e.NewValue;
            object oldValue = e.OldValue;
            this.UpdateDataContext(this.TrayPopupResolved, oldValue, newValue);
            this.UpdateDataContext(this.TrayToolTipResolved, oldValue, newValue);
            this.UpdateDataContext(base.ContextMenu, oldValue, newValue);
        }

        private void OnExit(object sender, EventArgs e)
        {
            this.Dispose();
        }

        private void OnIconSourcePropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            ImageSource newValue = (ImageSource) e.NewValue;
            if (!Util.IsDesignMode)
            {
                this.Icon = newValue.ToIcon();
            }
        }

        private void OnMouseEvent(MouseEvent me)
        {
            Action action = null;
            Action action2 = null;
            Action action3 = null;
            Hardcodet.Wpf.TaskbarNotification.Interop.Point cursorPosition;
            if (!this.IsDisposed)
            {
                switch (me)
                {
                    case MouseEvent.MouseMove:
                        this.RaiseTrayMouseMoveEvent();
                        return;

                    case MouseEvent.IconRightMouseDown:
                        this.RaiseTrayRightMouseDownEvent();
                        break;

                    case MouseEvent.IconLeftMouseDown:
                        this.RaiseTrayLeftMouseDownEvent();
                        break;

                    case MouseEvent.IconRightMouseUp:
                        this.RaiseTrayRightMouseUpEvent();
                        break;

                    case MouseEvent.IconLeftMouseUp:
                        this.RaiseTrayLeftMouseUpEvent();
                        break;

                    case MouseEvent.IconMiddleMouseDown:
                        this.RaiseTrayMiddleMouseDownEvent();
                        break;

                    case MouseEvent.IconMiddleMouseUp:
                        this.RaiseTrayMiddleMouseUpEvent();
                        break;

                    case MouseEvent.IconDoubleClick:
                        this.singleClickTimer.Change(-1, -1);
                        this.RaiseTrayMouseDoubleClickEvent();
                        break;

                    case MouseEvent.BalloonToolTipClicked:
                        this.RaiseTrayBalloonTipClickedEvent();
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("me", "Missing handler for mouse event flag: " + me);
                }
                cursorPosition = new Hardcodet.Wpf.TaskbarNotification.Interop.Point();
                WinApi.GetCursorPos(ref cursorPosition);
                bool flag = false;
                if (me.IsMatch(this.PopupActivation))
                {
                    if (me == MouseEvent.IconLeftMouseUp)
                    {
                        if (action == null)
                        {
                            action = delegate {
                                this.LeftClickCommand.ExecuteIfEnabled(this.LeftClickCommandParameter, this.LeftClickCommandTarget ?? this);
                                this.ShowTrayPopup(cursorPosition);
                            };
                        }
                        this.delayedTimerAction = action;
                        this.singleClickTimer.Change(WinApi.GetDoubleClickTime(), -1);
                        flag = true;
                    }
                    else
                    {
                        this.ShowTrayPopup(cursorPosition);
                    }
                }
                if (me.IsMatch(this.MenuActivation))
                {
                    if (me == MouseEvent.IconLeftMouseUp)
                    {
                        if (action2 == null)
                        {
                            action2 = delegate {
                                this.LeftClickCommand.ExecuteIfEnabled(this.LeftClickCommandParameter, this.LeftClickCommandTarget ?? this);
                                this.ShowContextMenu(cursorPosition);
                            };
                        }
                        this.delayedTimerAction = action2;
                        this.singleClickTimer.Change(WinApi.GetDoubleClickTime(), -1);
                        flag = true;
                    }
                    else
                    {
                        this.ShowContextMenu(cursorPosition);
                    }
                }
                if ((me == MouseEvent.IconLeftMouseUp) && !flag)
                {
                    if (action3 == null)
                    {
                        action3 = () => this.LeftClickCommand.ExecuteIfEnabled(this.LeftClickCommandParameter, this.LeftClickCommandTarget ?? this);
                    }
                    this.delayedTimerAction = action3;
                    this.singleClickTimer.Change(WinApi.GetDoubleClickTime(), -1);
                }
            }
        }

        private void OnTaskbarCreated()
        {
            this.IsTaskbarIconCreated = false;
            this.CreateTaskbarIcon();
        }

        private void OnToolTipChange(bool visible)
        {
            if (this.TrayToolTipResolved != null)
            {
                if (visible)
                {
                    if (!this.IsPopupOpen && !this.RaisePreviewTrayToolTipOpenEvent().Handled)
                    {
                        this.TrayToolTipResolved.IsOpen = true;
                        if (this.TrayToolTip != null)
                        {
                            RaiseToolTipOpenedEvent(this.TrayToolTip);
                        }
                        this.RaiseTrayToolTipOpenEvent();
                    }
                }
                else if (!this.RaisePreviewTrayToolTipCloseEvent().Handled)
                {
                    if (this.TrayToolTip != null)
                    {
                        RaiseToolTipCloseEvent(this.TrayToolTip);
                    }
                    this.TrayToolTipResolved.IsOpen = false;
                    this.RaiseTrayToolTipCloseEvent();
                }
            }
        }

        private void OnToolTipTextPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if ((this.TrayToolTipResolved == null) || (this.TrayToolTipResolved.Content is string))
            {
                this.CreateCustomToolTip();
            }
            this.WriteToolTipSettings();
        }

        private void OnTrayPopupPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != null)
            {
                SetParentTaskbarIcon((DependencyObject) e.OldValue, null);
            }
            if (e.NewValue != null)
            {
                SetParentTaskbarIcon((DependencyObject) e.NewValue, this);
            }
            this.CreatePopup();
        }

        private void OnTrayToolTipPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            this.CreateCustomToolTip();
            if (e.OldValue != null)
            {
                SetParentTaskbarIcon((DependencyObject) e.OldValue, null);
            }
            if (e.NewValue != null)
            {
                SetParentTaskbarIcon((DependencyObject) e.NewValue, this);
            }
            this.WriteToolTipSettings();
        }

        private void OnVisibilityPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (((Visibility) e.NewValue) == Visibility.Visible)
            {
                this.CreateTaskbarIcon();
            }
            else
            {
                this.RemoveTaskbarIcon();
            }
        }

        internal static RoutedEventArgs RaiseBalloonClosingEvent(DependencyObject target, TaskbarIcon source)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs(BalloonClosingEvent, source);
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        internal static RoutedEventArgs RaiseBalloonShowingEvent(DependencyObject target, TaskbarIcon source)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs(BalloonShowingEvent, source);
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        internal static RoutedEventArgs RaisePopupOpenedEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = PopupOpenedEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent()
        {
            return RaisePreviewTrayContextMenuOpenEvent(this);
        }

        internal static RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = PreviewTrayContextMenuOpenEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaisePreviewTrayPopupOpenEvent()
        {
            return RaisePreviewTrayPopupOpenEvent(this);
        }

        internal static RoutedEventArgs RaisePreviewTrayPopupOpenEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = PreviewTrayPopupOpenEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaisePreviewTrayToolTipCloseEvent()
        {
            return RaisePreviewTrayToolTipCloseEvent(this);
        }

        internal static RoutedEventArgs RaisePreviewTrayToolTipCloseEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = PreviewTrayToolTipCloseEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaisePreviewTrayToolTipOpenEvent()
        {
            return RaisePreviewTrayToolTipOpenEvent(this);
        }

        internal static RoutedEventArgs RaisePreviewTrayToolTipOpenEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = PreviewTrayToolTipOpenEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        internal static RoutedEventArgs RaiseToolTipCloseEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = ToolTipCloseEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        internal static RoutedEventArgs RaiseToolTipOpenedEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = ToolTipOpenedEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayBalloonTipClickedEvent()
        {
            return RaiseTrayBalloonTipClickedEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayBalloonTipClickedEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayBalloonTipClickedEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayBalloonTipClosedEvent()
        {
            return RaiseTrayBalloonTipClosedEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayBalloonTipClosedEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayBalloonTipClosedEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayBalloonTipShownEvent()
        {
            return RaiseTrayBalloonTipShownEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayBalloonTipShownEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayBalloonTipShownEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayContextMenuOpenEvent()
        {
            return RaiseTrayContextMenuOpenEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayContextMenuOpenEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayContextMenuOpenEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayLeftMouseDownEvent()
        {
            return RaiseTrayLeftMouseDownEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayLeftMouseDownEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayLeftMouseDownEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayLeftMouseUpEvent()
        {
            return RaiseTrayLeftMouseUpEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayLeftMouseUpEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayLeftMouseUpEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayMiddleMouseDownEvent()
        {
            return RaiseTrayMiddleMouseDownEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayMiddleMouseDownEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayMiddleMouseDownEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayMiddleMouseUpEvent()
        {
            return RaiseTrayMiddleMouseUpEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayMiddleMouseUpEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayMiddleMouseUpEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayMouseDoubleClickEvent()
        {
            RoutedEventArgs args = RaiseTrayMouseDoubleClickEvent(this);
            this.DoubleClickCommand.ExecuteIfEnabled(this.DoubleClickCommandParameter, this.DoubleClickCommandTarget ?? this);
            return args;
        }

        internal static RoutedEventArgs RaiseTrayMouseDoubleClickEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayMouseDoubleClickEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayMouseMoveEvent()
        {
            return RaiseTrayMouseMoveEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayMouseMoveEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayMouseMoveEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayPopupOpenEvent()
        {
            return RaiseTrayPopupOpenEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayPopupOpenEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayPopupOpenEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayRightMouseDownEvent()
        {
            return RaiseTrayRightMouseDownEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayRightMouseDownEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayRightMouseDownEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayRightMouseUpEvent()
        {
            return RaiseTrayRightMouseUpEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayRightMouseUpEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayRightMouseUpEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayToolTipCloseEvent()
        {
            return RaiseTrayToolTipCloseEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayToolTipCloseEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayToolTipCloseEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        protected RoutedEventArgs RaiseTrayToolTipOpenEvent()
        {
            return RaiseTrayToolTipOpenEvent(this);
        }

        internal static RoutedEventArgs RaiseTrayToolTipOpenEvent(DependencyObject target)
        {
            if (target == null)
            {
                return null;
            }
            RoutedEventArgs args = new RoutedEventArgs {
                RoutedEvent = TrayToolTipOpenEvent
            };
            RoutedEventHelper.RaiseEvent(target, args);
            return args;
        }

        public static void RemoveBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler)
        {
            RoutedEventHelper.RemoveHandler(element, BalloonClosingEvent, handler);
        }

        public static void RemoveBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler)
        {
            RoutedEventHelper.RemoveHandler(element, BalloonShowingEvent, handler);
        }

        public static void RemovePopupOpenedHandler(DependencyObject element, RoutedEventHandler handler)
        {
            RoutedEventHelper.RemoveHandler(element, PopupOpenedEvent, handler);
        }

        private void RemoveTaskbarIcon()
        {
            lock (this)
            {
                if (this.IsTaskbarIconCreated)
                {
                    Util.WriteIconData(ref this.iconData, NotifyCommand.Delete, IconDataMembers.Message);
                    this.IsTaskbarIconCreated = false;
                }
            }
        }

        public static void RemoveToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler)
        {
            RoutedEventHelper.RemoveHandler(element, ToolTipCloseEvent, handler);
        }

        public static void RemoveToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler)
        {
            RoutedEventHelper.RemoveHandler(element, ToolTipOpenedEvent, handler);
        }

        public void ResetBalloonCloseTimer()
        {
            if (!this.IsDisposed)
            {
                lock (this)
                {
                    this.balloonCloseTimer.Change(-1, -1);
                }
            }
        }

        protected void SetCustomBalloon(Popup value)
        {
            base.SetValue(CustomBalloonPropertyKey, value);
        }

        public static void SetParentTaskbarIcon(DependencyObject d, TaskbarIcon value)
        {
            d.SetValue(ParentTaskbarIconProperty, value);
        }

        protected void SetTrayPopupResolved(Popup value)
        {
            base.SetValue(TrayPopupResolvedPropertyKey, value);
        }

        protected void SetTrayToolTipResolved(ToolTip value)
        {
            base.SetValue(TrayToolTipResolvedPropertyKey, value);
        }

        private void SetVersion()
        {
            this.iconData.VersionOrTimeout = 4;
            bool flag = WinApi.Shell_NotifyIcon(NotifyCommand.SetVersion, ref this.iconData);
            if (!flag)
            {
                this.iconData.VersionOrTimeout = 3;
                flag = Util.WriteIconData(ref this.iconData, NotifyCommand.SetVersion);
            }
            if (!flag)
            {
                this.iconData.VersionOrTimeout = 0;
                flag = Util.WriteIconData(ref this.iconData, NotifyCommand.SetVersion);
            }
        }

        public void ShowBalloonTip(string title, string message, BalloonIcon symbol)
        {
            lock (this)
            {
                this.ShowBalloonTip(title, message, symbol.GetBalloonFlag(), IntPtr.Zero);
            }
        }

        public void ShowBalloonTip(string title, string message, System.Drawing.Icon customIcon)
        {
            if (customIcon == null)
            {
                throw new ArgumentNullException("customIcon");
            }
            lock (this)
            {
                this.ShowBalloonTip(title, message, BalloonFlags.User, customIcon.Handle);
            }
        }

        private void ShowBalloonTip(string title, string message, BalloonFlags flags, IntPtr balloonIconHandle)
        {
            this.EnsureNotDisposed();
            this.iconData.BalloonText = message ?? string.Empty;
            this.iconData.BalloonTitle = title ?? string.Empty;
            this.iconData.BalloonFlags = flags;
            this.iconData.CustomBalloonIconHandle = balloonIconHandle;
            Util.WriteIconData(ref this.iconData, NotifyCommand.Modify, IconDataMembers.Info | IconDataMembers.Icon);
        }

        private void ShowContextMenu(Hardcodet.Wpf.TaskbarNotification.Interop.Point cursorPosition)
        {
            if ((!this.IsDisposed && !this.RaisePreviewTrayContextMenuOpenEvent().Handled) && (base.ContextMenu != null))
            {
                base.ContextMenu.Placement = PlacementMode.AbsolutePoint;
                base.ContextMenu.HorizontalOffset = cursorPosition.X;
                base.ContextMenu.VerticalOffset = cursorPosition.Y;
                base.ContextMenu.IsOpen = true;
                WinApi.SetForegroundWindow(this.messageSink.MessageWindowHandle);
                this.RaiseTrayContextMenuOpenEvent();
            }
        }

        public void ShowCustomBalloon(UIElement balloon, PopupAnimation animation, int? timeout)
        {
            Action action2 = null;
            if (!Application.Current.Dispatcher.CheckAccess())
            {
                if (action2 == null)
                {
                    action2 = () => this.ShowCustomBalloon(balloon, animation, timeout);
                }
                Action method = action2;
                Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, method);
            }
            else
            {
                if (balloon == null)
                {
                    throw new ArgumentNullException("balloon");
                }
                if (timeout.HasValue && (timeout < 500))
                {
                    string format = "Invalid timeout of {0} milliseconds. Timeout must be at least 500 ms";
                    format = string.Format(format, timeout);
                    throw new ArgumentOutOfRangeException("timeout", format);
                }
                this.EnsureNotDisposed();
                lock (this)
                {
                    this.CloseBalloon();
                }
                Popup target = new Popup {
                    AllowsTransparency = true
                };
                this.UpdateDataContext(target, null, base.DataContext);
                target.PopupAnimation = animation;
                target.Child = balloon;
                target.Placement = PlacementMode.AbsolutePoint;
                target.StaysOpen = true;
                Hardcodet.Wpf.TaskbarNotification.Interop.Point trayLocation = TrayInfo.GetTrayLocation();
                target.HorizontalOffset = trayLocation.X - 1;
                target.VerticalOffset = trayLocation.Y - 1;
                lock (this)
                {
                    this.SetCustomBalloon(target);
                }
                SetParentTaskbarIcon(balloon, this);
                RaiseBalloonShowingEvent(balloon, this);
                target.IsOpen = true;
                if (timeout.HasValue)
                {
                    this.balloonCloseTimer.Change(timeout.Value, -1);
                }
            }
        }

        private void ShowTrayPopup(Hardcodet.Wpf.TaskbarNotification.Interop.Point cursorPosition)
        {
            if ((!this.IsDisposed && !this.RaisePreviewTrayPopupOpenEvent().Handled) && (this.TrayPopup != null))
            {
                this.TrayPopupResolved.Placement = PlacementMode.AbsolutePoint;
                this.TrayPopupResolved.HorizontalOffset = cursorPosition.X;
                this.TrayPopupResolved.VerticalOffset = cursorPosition.Y;
                this.TrayPopupResolved.IsOpen = true;
                WinApi.SetForegroundWindow(this.messageSink.MessageWindowHandle);
                if (this.TrayPopup != null)
                {
                    RaisePopupOpenedEvent(this.TrayPopup);
                }
                this.RaiseTrayPopupOpenEvent();
            }
        }

        private static void ToolTipTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarIcon) d).OnToolTipTextPropertyChanged(e);
        }

        private static void TrayPopupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarIcon) d).OnTrayPopupPropertyChanged(e);
        }

        private static void TrayToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarIcon) d).OnTrayToolTipPropertyChanged(e);
        }

        private void UpdateDataContext(FrameworkElement target, object oldDataContextValue, object newDataContextValue)
        {
            if (((target != null) && !target.IsDataContextDataBound()) && (object.ReferenceEquals(this, target.DataContext) || object.Equals(oldDataContextValue, target.DataContext)))
            {
                target.DataContext = newDataContextValue ?? this;
            }
        }

        private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarIcon) d).OnVisibilityPropertyChanged(e);
        }

        private void WriteToolTipSettings()
        {
            this.iconData.ToolTipText = this.ToolTipText;
            if (((this.messageSink.Version == NotifyIconVersion.Vista) && string.IsNullOrEmpty(this.iconData.ToolTipText)) && (this.TrayToolTipResolved != null))
            {
                this.iconData.ToolTipText = "ToolTip";
            }
            Util.WriteIconData(ref this.iconData, NotifyCommand.Modify, IconDataMembers.Tip);
        }

        public Popup CustomBalloon
        {
            get
            {
                return (Popup) base.GetValue(CustomBalloonProperty);
            }
        }

        public ICommand DoubleClickCommand
        {
            get
            {
                return (ICommand) base.GetValue(DoubleClickCommandProperty);
            }
            set
            {
                base.SetValue(DoubleClickCommandProperty, value);
            }
        }

        public object DoubleClickCommandParameter
        {
            get
            {
                return base.GetValue(DoubleClickCommandParameterProperty);
            }
            set
            {
                base.SetValue(DoubleClickCommandParameterProperty, value);
            }
        }

        public IInputElement DoubleClickCommandTarget
        {
            get
            {
                return (IInputElement) base.GetValue(DoubleClickCommandTargetProperty);
            }
            set
            {
                base.SetValue(DoubleClickCommandTargetProperty, value);
            }
        }

        [Browsable(false)]
        public System.Drawing.Icon Icon
        {
            get
            {
                return this.icon;
            }
            set
            {
                this.icon = value;
                this.iconData.IconHandle = (value == null) ? IntPtr.Zero : this.icon.Handle;
                Util.WriteIconData(ref this.iconData, NotifyCommand.Modify, IconDataMembers.Icon);
            }
        }

        [Description("Sets the displayed taskbar icon."), Category("NotifyIcon")]
        public ImageSource IconSource
        {
            get
            {
                return (ImageSource) base.GetValue(IconSourceProperty);
            }
            set
            {
                base.SetValue(IconSourceProperty, value);
            }
        }

        public bool IsDisposed { get; private set; }

        private bool IsPopupOpen
        {
            get
            {
                Popup trayPopupResolved = this.TrayPopupResolved;
                ContextMenu contextMenu = base.ContextMenu;
                Popup customBalloon = this.CustomBalloon;
                if (((trayPopupResolved == null) || !trayPopupResolved.IsOpen) && ((contextMenu == null) || !contextMenu.IsOpen))
                {
                    return ((customBalloon != null) && customBalloon.IsOpen);
                }
                return true;
            }
        }

        public bool IsTaskbarIconCreated { get; private set; }

        public ICommand LeftClickCommand
        {
            get
            {
                return (ICommand) base.GetValue(LeftClickCommandProperty);
            }
            set
            {
                base.SetValue(LeftClickCommandProperty, value);
            }
        }

        public object LeftClickCommandParameter
        {
            get
            {
                return base.GetValue(LeftClickCommandParameterProperty);
            }
            set
            {
                base.SetValue(LeftClickCommandParameterProperty, value);
            }
        }

        public IInputElement LeftClickCommandTarget
        {
            get
            {
                return (IInputElement) base.GetValue(LeftClickCommandTargetProperty);
            }
            set
            {
                base.SetValue(LeftClickCommandTargetProperty, value);
            }
        }

        [Category("NotifyIcon"), Description("Defines what mouse events display the context menu.")]
        public PopupActivationMode MenuActivation
        {
            get
            {
                return (PopupActivationMode) base.GetValue(MenuActivationProperty);
            }
            set
            {
                base.SetValue(MenuActivationProperty, value);
            }
        }

        [Description("Defines what mouse events display the TaskbarIconPopup."), Category("NotifyIcon")]
        public PopupActivationMode PopupActivation
        {
            get
            {
                return (PopupActivationMode) base.GetValue(PopupActivationProperty);
            }
            set
            {
                base.SetValue(PopupActivationProperty, value);
            }
        }

        public bool SupportsCustomToolTips
        {
            get
            {
                return (this.messageSink.Version == NotifyIconVersion.Vista);
            }
        }

        [Description("Alternative to a fully blown ToolTip, which is only displayed on Vista and above."), Category("NotifyIcon")]
        public string ToolTipText
        {
            get
            {
                return (string) base.GetValue(ToolTipTextProperty);
            }
            set
            {
                base.SetValue(ToolTipTextProperty, value);
            }
        }

        [Description("Displayed as a Popup if the user clicks on the taskbar icon."), Category("NotifyIcon")]
        public UIElement TrayPopup
        {
            get
            {
                return (UIElement) base.GetValue(TrayPopupProperty);
            }
            set
            {
                base.SetValue(TrayPopupProperty, value);
            }
        }

        [Category("NotifyIcon")]
        public Popup TrayPopupResolved
        {
            get
            {
                return (Popup) base.GetValue(TrayPopupResolvedProperty);
            }
        }

        [Category("NotifyIcon"), Description("Custom UI element that is displayed as a tooltip. Only on Vista and above")]
        public UIElement TrayToolTip
        {
            get
            {
                return (UIElement) base.GetValue(TrayToolTipProperty);
            }
            set
            {
                base.SetValue(TrayToolTipProperty, value);
            }
        }

        [Browsable(true), Bindable(true), Category("NotifyIcon")]
        public ToolTip TrayToolTipResolved
        {
            get
            {
                return (ToolTip) base.GetValue(TrayToolTipResolvedProperty);
            }
        }
    }
}

